package com.jinzhi.jzweb.service.impl.modelConfig;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.jinzhi.common.service.DictService;
import com.jinzhi.common.utils.Result;
import com.jinzhi.common.utils.StringUtil;
import com.jinzhi.jzweb.dao.modelConfig.DeclareDao;
import com.jinzhi.jzweb.domain.ExaminationBatchDO;
import com.jinzhi.jzweb.domain.modelConfig.DeclareDO;
import com.jinzhi.jzweb.domain.modelConfig.DeclareFileDO;
import com.jinzhi.jzweb.domain.modelConfig.DeclareTypeDO;
import com.jinzhi.jzweb.domain.modelConfig.DeclareVo;
import com.jinzhi.jzweb.service.ExaminationBatchService;
import com.jinzhi.jzweb.service.modelConfig.DeclareFileService;
import com.jinzhi.jzweb.service.modelConfig.DeclareService;
import com.jinzhi.jzweb.service.modelConfig.DeclareTypeService;
import com.jinzhi.jzweb.utils.ZipFileUtils;
import org.aspectj.weaver.patterns.Declare;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.jinzhi.common.base.CoreServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 
 * <pre>
 * 申报主体信息表
 * </pre>
 * <small> 2024-01-10 09:37:33 | lance</small>
 */
@Service
public class DeclareServiceImpl extends CoreServiceImpl<DeclareDao, DeclareDO> implements DeclareService {

    private final DeclareTypeService declareTypeService;
    private final DeclareFileService declareFileService;
    private final DictService dictService;
    private final ExaminationBatchService examinationBatchService;


    public DeclareServiceImpl(DeclareTypeService declareTypeService, DeclareFileService declareFileService, DictService dictService, ExaminationBatchService examinationBatchService) {
        this.declareTypeService = declareTypeService;
        this.declareFileService = declareFileService;
        this.dictService = dictService;
        this.examinationBatchService = examinationBatchService;
    }

    /**
     * 压缩包下载验证
     * @param declareDO
     * @return
     */
    @Override
    public Result declareEfficiency(DeclareDO declareDO) {
        EntityWrapper<DeclareDO> wrapper = new EntityWrapper<>();
        if(null!=declareDO.getIdList() && !declareDO.getIdList().isEmpty() ){
            wrapper.in("id",declareDO.getIdList());
//            wrapper.eq("id",declareDO.getId());
        }
        //用来判断是否存在可导出的数据
        boolean flag = false;
        List<DeclareDO> declareDOS = this.selectList(wrapper);
        if(null == declareDOS || declareDOS.isEmpty()) {
            return Result.fail("没有可导出的数据");
        } else {
            for (DeclareDO aDo : declareDOS) {
                if(flag){
                    break;
                }
                //查询当前申报下的所有类型
                EntityWrapper<DeclareTypeDO> declareTypeDOEntityWrapper = new EntityWrapper<>();
                declareTypeDOEntityWrapper.eq("declare_id",aDo.getId());
                if(null != declareDO.getType()){
                    declareTypeDOEntityWrapper.eq("type",declareDO.getType());
                }
                List<DeclareTypeDO> declareTypeDOS = declareTypeService.selectList(declareTypeDOEntityWrapper);
                if(null != declareTypeDOS && !declareTypeDOS.isEmpty()){
                    for (DeclareTypeDO declareTypeDO : declareTypeDOS) {
                        //查询当前类型下的文件
                        EntityWrapper<DeclareFileDO> fileWrapper = new EntityWrapper<>();
                        fileWrapper.eq("declare_type_id", declareTypeDO.getId());
                        List<DeclareFileDO> declareFileDOS = declareFileService.selectList(fileWrapper);
                        if(null != declareFileDOS && !declareFileDOS.isEmpty()){
                            flag = true;
                            break;
                        }
                    }
                }
            }
        }
        if(flag){
            return Result.ok();
        }else{
            return Result.fail("没有可导出的数据");
        }
    }

    /**
     * 压缩包下载
     * @param declareDO
     * @param response
     * @return
     * @throws IOException
     */
    @Override
    public Result fileDownload(DeclareDO declareDO, HttpServletResponse response) throws IOException {
        //查询磁盘存储路径
        Map<String, String> map =new HashMap<>();
        map.put("type","foundZip");
        map.put("name","foundZip");
        String foundZip = dictService.selDicBy(map);
        //查询所有申报
        EntityWrapper<DeclareDO> wrapper = new EntityWrapper<>();
        if(null!=declareDO.getIdList() && !declareDO.getIdList().isEmpty() ){
            wrapper.in("id",declareDO.getIdList());
//            wrapper.eq("id",declareDO.getId());
        }
        //创建最外层文件夹
        String firstName = "申报导出信息" + System.currentTimeMillis();
        File file = new File(foundZip + File.separator + firstName);
        file.mkdir();
        List<DeclareDO> list = this.selectList(wrapper);
        //遍历申报
        for (DeclareDO aDo : list) {
            String baName = aDo.getOrgName() +"_"+ aDo.getPhone() +"_"+ System.currentTimeMillis();
            baName = baName.replaceAll("/","-");
            //查询当前申报下的类型
            EntityWrapper<DeclareTypeDO> declareTypeDOEntityWrapper = new EntityWrapper<>();
            declareTypeDOEntityWrapper.eq("declare_id",aDo.getId());
            if(null != declareDO.getType()){
                declareTypeDOEntityWrapper.eq("type",declareDO.getType());
            }
            List<DeclareTypeDO> declareTypeDOS = declareTypeService.selectList(declareTypeDOEntityWrapper);

            if(null != declareTypeDOS && !declareTypeDOS.isEmpty()){
                for (DeclareTypeDO declareTypeDO : declareTypeDOS) {
                    //查询当前类型下的文件
                    EntityWrapper<DeclareFileDO> fileWrapper = new EntityWrapper<>();
                    fileWrapper.eq("declare_type_id", declareTypeDO.getId());
                    List<DeclareFileDO> declareFileDOS = declareFileService.selectList(fileWrapper);
                    if(null != declareFileDOS && !declareFileDOS.isEmpty()){
                        /**
                         * baName 最外层文件名称命名规则：单位名称 + phone + 当前时间戳
                         * fileName 当前文件名称命名规则：教师姓名/法定联系人 + 联系方式 + 当前时间戳
                         */
                        String fileName = declareTypeDO.getName() +"_"+ declareTypeDO.getPhone() +"_"+ System.currentTimeMillis();
                        fileName= fileName.replaceAll("/","-");
                        unzip(declareFileDOS, foundZip, firstName,baName, fileName,declareTypeDO.getType());
                        
                    }
                }
            }

        }

        //调用文件接口
        return Result.ok(foundZip(file,response));
    }

    @Override
    @Transactional
    public Result insertDeclare(DeclareDO declareDO,Long userId) {
        if(declareDO.getDeclareTypeDOS().isEmpty()){
            return Result.fail("没有填写申报项");
        }
        //新增申报主体
        declareDO.setCreaterId(userId);
        if(!detection(declareDO.getDeclareTypeDOS())){
            return Result.fail("申报项信息填写不完整或不符合申报规则");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        int year = Integer.parseInt(sdf.format(new Date()));
    /*    List<DeclareDO> doList = this.selectList(new EntityWrapper<DeclareDO>()
                .eq("org_id",declareDO.getOrgId())
                .andNew("YEAR(creater_date) = {0}",year));
        if(!doList.isEmpty()){
            return Result.fail("无法重复申报");
        }*/

        boolean aBoolean = this.insert(declareDO);
        if(!aBoolean){
            return Result.fail();
        }

        //新增申报类型
        for (int i = 0; i < declareDO.getDeclareTypeDOS().size(); i++) {
            declareDO.getDeclareTypeDOS().get(i).setDeclareId(declareDO.getId());
            declareTypeService.insert(declareDO.getDeclareTypeDOS().get(i));
            if(declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().isEmpty()){
                continue;
            }
            for (int j = 0; j < declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().size(); j++) {
                //新增文件
                declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().get(j).setDeclareTypeId(declareDO.getDeclareTypeDOS().get(i).getId());
                declareFileService.insert(declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().get(j));
            }
        }
        return Result.ok();
    }


    private boolean detection(List<DeclareTypeDO> declareTypeDOS){
        boolean isNull = true;
        for (int i = 0; i < declareTypeDOS.size(); i++) {
            if(declareTypeDOS.get(i).getType() == 2){
                //验证优秀培训教师
                if(StringUtil.isNull(declareTypeDOS.get(i).getName())||StringUtil.isNull(declareTypeDOS.get(i).getPhone())
                        ||StringUtil.isNull(declareTypeDOS.get(i).getCard())){
                    return isNull = false;
                }

                //验证是否申报过培训教师
                String card = declareTypeDOS.get(i).getCard();//获取申报的教师身份信息
                Integer type = declareTypeDOS.get(i).getType(); //获取申报的类型
                Integer certType = declareTypeDOS.get(i).getCertType(); //幼儿照护产后恢复类型
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
                int year = Integer.parseInt(sdf.format(new Date()));
                Wrapper<DeclareTypeDO> wrapper =new EntityWrapper();
                wrapper.eq("card",card);
                wrapper.eq("type",type);
                wrapper.eq("cert_type",certType);
                wrapper.andNew("YEAR(creater_date) = {0}",year);
                List<DeclareTypeDO> declareTypeDO = declareTypeService.selectList(wrapper);
                if (declareTypeDO!=null){
                    if (declareTypeDO.size()>0){
                        return isNull = false;
                    }
                }else {
                    return isNull = false;
                }

            }else if(declareTypeDOS.get(i).getType() == 4){
                //特殊贡献
                if(StringUtil.isNull(declareTypeDOS.get(i).getName())||StringUtil.isNull(declareTypeDOS.get(i).getPhone())
                        ||StringUtil.isNull(declareTypeDOS.get(i).getSection())||StringUtil.isNull(declareTypeDOS.get(i).getCard())){
                    return isNull = false;
                }
            } else if (declareTypeDOS.get(i).getType() == 3) {
                //考务工作者
                if(StringUtil.isNull(declareTypeDOS.get(i).getName())||StringUtil.isNull(declareTypeDOS.get(i).getPhone())
                        ||StringUtil.isNull(declareTypeDOS.get(i).getCard())){
                    return isNull = false;
                }
            } else{
                //其他
                if(StringUtil.isNull(declareTypeDOS.get(i).getName())||StringUtil.isNull(declareTypeDOS.get(i).getPhone())
                        ||StringUtil.isNull(declareTypeDOS.get(i).getSection())){
                    return isNull = false;
                }
            }
        }
        return isNull;
    }



    @Override
    @Transactional
    public Result updateDeclare(DeclareDO declareDO) {
        declareDO.setStatus(0);
        boolean aBoolean = this.updateById(declareDO);
        if(!aBoolean){
            return Result.fail();
        }
        if(!declareDO.getDeclareTypeDOS().isEmpty()){
            //删除文件信息
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
            int year = Integer.parseInt(sdf.format(new Date()));
            for (int i = 0; i < declareDO.getDeclareTypeDOS().size(); i++) {
                declareFileService.delete(new EntityWrapper<DeclareFileDO>().eq("declare_type_id",declareDO.getDeclareTypeDOS().get(i).getId()).andNew("YEAR(creater_date) = {0}",year));
                //删除类型
                declareTypeService.delete(new EntityWrapper<DeclareTypeDO>().eq("declare_id",declareDO.getId()).andNew("YEAR(creater_date) = {0}",year));
            }
        }
        //新增申报类型
        if(!declareDO.getDeclareTypeDOS().isEmpty()){
            for (int i = 0; i < declareDO.getDeclareTypeDOS().size(); i++) {
                declareDO.getDeclareTypeDOS().get(i).setDeclareId(declareDO.getId());
                declareTypeService.insert(declareDO.getDeclareTypeDOS().get(i));
                if(declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().isEmpty()){
                    continue;
                }
                for (int j = 0; j < declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().size(); j++) {
                    //新增文件
                    declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().get(j).setDeclareTypeId(declareDO.getDeclareTypeDOS().get(i).getId());
                    declareFileService.insert(declareDO.getDeclareTypeDOS().get(i).getDeclareFileDOS().get(j));
                }
            }
        }
        return Result.ok();
    }

    @Override
    public Result verify(String orgName) {
        LocalDateTime start = LocalDateTime.of(2023, 1, 22, 0, 0, 0);
        LocalDateTime end = LocalDateTime.of(2026, 2, 10, 0, 0, 0);
        List<ExaminationBatchDO> examinationBatchDOS = examinationBatchService.selectList(
                new EntityWrapper<ExaminationBatchDO>().like("name",orgName)
        .ge("start_time",start)
        .lt("start_time",end));
        if(examinationBatchDOS.isEmpty()){
            return Result.fail("没有证书无法推荐");
        }


        Boolean isc = false;
        Boolean isy = false;
        for(ExaminationBatchDO ex:examinationBatchDOS){
            if(isy == false && ex.getName().indexOf("幼儿照护")!=-1){
                isy = true;
            }
            if(isc == false && ex.getName().indexOf("产后恢复")!=-1){
                isc = true;
            }
        }
        if(isc==true && isy==true){
            //拥有两个证书
            return Result.ok(2);
        }else if(isc==true){
            //有产后恢复证书
            return Result.ok(0);
        }else if(isy==true){
            //有幼儿照护证书
            return Result.ok(0);
        }else{
            //无证书
            return Result.ok(1);
        }
    }

    @Override
    public Result getDeclareByCreaterId(Long createrId,Long declareReadyId) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        int year = Integer.parseInt(sdf.format(new Date()));
        List<DeclareDO> doList =  this.selectList(new EntityWrapper<DeclareDO>()
                .eq("creater_id",createrId)
                .eq("declare_ready_id",declareReadyId)
                .andNew("YEAR(creater_date) = {0}",year)
        .orderBy("creater_date",false));
        if(doList.isEmpty()){
            return Result.ok();
        }
        List<DeclareTypeDO> dos =  declareTypeService.selectList(new EntityWrapper<DeclareTypeDO>().eq("declare_id",doList.get(0).getId()));
        if(dos.isEmpty()){
            return Result.ok(doList);
        }
        for (int i = 0; i < dos.size(); i++) {
             dos.get(i).setDeclareFileDOS(declareFileService.selectList(new EntityWrapper<DeclareFileDO>().eq("declare_type_id",dos.get(i).getId())));
        }
        doList.get(0).setDeclareTypeDOS(dos);
        return  Result.ok(doList);
    }

    /**
     * 导出申报汇总数据
     */
    @Override
    public List<DeclareVo> exportList(DeclareDO declareDO, HttpServletResponse response) throws IOException {
        //查询所有申报
        EntityWrapper<DeclareDO> wrapper = new EntityWrapper<>();
        if(null!=declareDO.getIdList() && !declareDO.getIdList().isEmpty() ){
            wrapper.in("id",declareDO.getIdList());
//            wrapper.eq("id",declareDO.getId());
        }
        List<DeclareDO> list = this.selectList(wrapper);
        List<DeclareVo> resultList = new ArrayList<>();//存储导出信息
        if(null != list && !list.isEmpty()){
            //遍历申报
            for (DeclareDO aDo : list) {
                //查询当前申报下的类型
                EntityWrapper<DeclareTypeDO> declareTypeDOEntityWrapper = new EntityWrapper<>();
                declareTypeDOEntityWrapper.eq("declare_id",aDo.getId());
                if(null != declareDO.getType()){
                    declareTypeDOEntityWrapper.eq("type",declareDO.getType());
                }
                //查询申报类型
                List<DeclareTypeDO> declareTypeDOS = declareTypeService.selectList(declareTypeDOEntityWrapper);
                if(null != declareTypeDOS && !declareTypeDOS.isEmpty()){
                    for (DeclareTypeDO declareTypeDO : declareTypeDOS) {
                        DeclareVo declareVo = new DeclareVo();
                        BeanUtils.copyProperties(aDo,declareVo);
                        declareVo.setDeclareName(aDo.getOrgName());//单位名称
                        declareVo.setDeclarePhone(aDo.getPhone());//单位联系电话
                        declareVo.setTypeName(declareTypeDO.getName());//教师姓名/法定联系人
                        declareVo.setSection(declareTypeDO.getSection());//申报人部门/单位
                        declareVo.setTypePhone(declareTypeDO.getPhone());//申报联系电话
                        declareVo.setStatus(getStatusName(aDo.getStatus()));//审核状态
                        declareVo.setType(this.getTypeName(declareTypeDO.getType()));//申报类型
                        declareVo.setCard(declareTypeDO.getCard());//身份证号码
                        declareVo.setCertType(this.getCertType(declareTypeDO.getCertType()));//证书类型
                        declareVo.setRemark(aDo.getRemark());
                        resultList.add(declareVo);
                    }
                }

            }
        }

        return resultList;

    }


    //获取状态名称
    public String getStatusName(Integer status){
        switch (status){
            case 0:
                return  "未审核" ;
            case 1:
                return  "审核通过";
            case 2:
                return "审核拒绝";
            default:
                return "";
        }
    }

    //通过类型获取名称
    public String getTypeName(Integer type){
        switch (type){
            case 1:
                return  "实习单位" ;
            case 2:
                return  "优秀培训教师";
            case 3:
                return "优秀考务工作者";
            case 4:
                return "优秀组织管理奖";
            case 5:
                return "优秀案例";
            default:
                return "";
        }
    }

    //获取证书类型
    public String getCertType(Integer certType){
        switch (certType){
            case 1:
                return  "幼儿照护" ;
            case 2:
                return  "产后恢复";
            default:
                return "";
        }
    }


    /**
     * 拼接节点文件
     * @param fileDOS
     * @param foundZip
     * @param baName 当前文件父级名称
     * @param fileName 当前文件名称
     * @param firstName 最外层文件名称
     * @param type 申报类型
     * @return
     * @throws IOException
     */
    private File unzip(List<DeclareFileDO> fileDOS, String foundZip, String firstName,String baName,String fileName,Integer type) throws IOException{
        String typeName = getTypeName(type);
        //创建资源的类型文件夹
        File typeFile = new File(foundZip + File.separator + firstName + File.separator + typeName);
        if(!typeFile.exists()){
            typeFile.mkdir();
        }
        //创建资源临时文件夹
        File file = new File(foundZip + File.separator + firstName + File.separator + typeName + File.separator + baName);
        if(!file.exists()){
            file.mkdir();
        }
        File file1 = new File(foundZip + File.separator + firstName + File.separator + typeName + File.separator + baName + File.separator + fileName);
        if(!file1.exists()){
            file1.mkdir();
        }
        fileWrite(file1.getPath(),fileDOS);

        return file;
    }



    /**
     * 用文件流的形式写入文件
     * @param path
     * @param declareFiles
     * @throws IOException
     */
    private void fileWrite(String path,List<DeclareFileDO> declareFiles) throws IOException {
        for (int i = 0; i < declareFiles.size(); i++) {
            URL url = new URL(declareFiles.get(i).getFile());
            String[] strings =  url.getFile().split("/");
            String fileName = strings[strings.length-1];
            System.out.println(fileName);
            URLConnection conn = url.openConnection();
            // 从连接中获取输入流
            InputStream in = conn.getInputStream();
            File tempFile = new File(path,fileName);
            // 创建一个输出流，将映像写入临时文件
            FileOutputStream out = new FileOutputStream(tempFile);
            // 从输入流中读取文件并将其写入输出流
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
            // 关闭输入和输出流
            in.close();
            out.close();
        }
    }


    /**
     * 封装文件接口
     */
    private byte[] foundZip(File files,HttpServletResponse response) throws IOException {
        byte[] bytes = new byte[1024];
        try {
            List<File> file = new ArrayList<>();
            String fileName = files.getPath();
            file.add(files);
            fileName = fileName + ".zip";
            System.out.println("Downloaded Zip saved as"+fileName);
            //压缩文件
            ZipFileUtils.generateZip(new File(fileName), file, false);
            File filess = new File(fileName);
            //上传成功后删除临时文件
            ZipFileUtils.download(filess,response);
            deleteFileByIO(filess.getPath());
            deleteFileByIO(files.getPath());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            deleteFileByIO(files.getPath());
        }

        return bytes;
    }

    /**
     * 通过递归逐层删除文件信息
     *
     * @param filePath
     */
    public static void deleteFileByIO(String filePath) {
        File file = new File(filePath);
        File[] list = file.listFiles();
        if (list != null) {
            for (File temp : list) {
                deleteFileByIO(temp.getAbsolutePath());
            }
        }
        file.delete();
    }



}
